﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Simpletron;
using Simpletron.Events;

namespace Simpletron_Tester
{
  class Program
  {
    public static readonly string FullAdder = "FullAdder";
    public static readonly string GreaterOfTwo = "GreaterOfTwo";

    static void Main(string[] args)
    {
      Dictionary<string, SimpleApp> apps = new Dictionary<string, SimpleApp>();
      apps.Add(FullAdder, SimpleApp.Create(FullAdder));
      apps.Add(GreaterOfTwo, SimpleApp.Create(GreaterOfTwo));
      
      apps[FullAdder].Add(SimpletronOpCodes.Read    , 20);
      apps[FullAdder].Add(SimpletronOpCodes.Read    , 21);
      apps[FullAdder].Add(SimpletronOpCodes.Load    , 20);
      apps[FullAdder].Add(SimpletronOpCodes.Add     , 21);
      apps[FullAdder].Add(SimpletronOpCodes.Store   , 22);
      apps[FullAdder].Add(SimpletronOpCodes.Write   , 22);
      apps[FullAdder].Add(SimpletronOpCodes.Halt    , 0);

      apps[GreaterOfTwo].Add(SimpletronOpCodes.Read       , 20);
      apps[GreaterOfTwo].Add(SimpletronOpCodes.Read       , 21);
      apps[GreaterOfTwo].Add(SimpletronOpCodes.Load       , 20);
      apps[GreaterOfTwo].Add(SimpletronOpCodes.Subtract   , 21);
      apps[GreaterOfTwo].Add(SimpletronOpCodes.BranchNeg  , 7);
      apps[GreaterOfTwo].Add(SimpletronOpCodes.Write      , 20);
      apps[GreaterOfTwo].Add(SimpletronOpCodes.Halt       , 0);
      apps[GreaterOfTwo].Add(SimpletronOpCodes.Write      , 21);
      apps[GreaterOfTwo].Add(SimpletronOpCodes.Halt       , 0);
      
      ExecutionEngien engien = new ExecutionEngien();
           
      engien.RaiseInputRequestEvent   += (RaiseInputRequestHandle);
      engien.RaiseOutputAwaitsEvent   += (RaiseOutputAwaitsHandle);
      engien.BeginLoadingEvent        += (BeginLoadingEventHandler);
      engien.LoadingEvent             += (LoadingEventHandler);
      engien.EndLoadingEvent          += (EndLoadingEventHandler);

      engien.Load(apps[GreaterOfTwo]);
      engien.Start();
    }

    static void BeginLoadingEventHandler(LoadingEventArg arg)
    {
      Console.WriteLine(string.Format("Loading: {0}", arg.Application.Name));
    }

    static void LoadingEventHandler(LoadingEventArg arg)
    {
      Console.WriteLine(string.Format("Loaded {0:0.0}%", arg.Percent));
    }

    static void EndLoadingEventHandler(LoadingEventArg obj)
    {
      Console.WriteLine("Loading Complet");
    }

    static void RaiseOutputAwaitsHandle(IOutput output)
    {
      Console.WriteLine(string.Format("Simpletron Output: {0}", output.GetOutput()));
    }

    static void RaiseInputRequestHandle(IInput input)
    {
      Console.Write(string.Format("Simpletron Input: "));
      var str = Console.ReadLine();

      int value;

      if (int.TryParse(str, out value))
      {
        input.SetInput(value);
      }
      else 
      {
        input.SetInput(0);
      }
    }
  }
}
